/**
 * Copyright (c) [2025] [AGIROS] 
 * [travoddsgen] is licensed under Mulan PSL v2. 
 * You can use this software according to the terms and conditions of the Mulan PSL v2. 
 * You may obtain a copy of Mulan PSL v2 at: 
 *          http://license.coscl.org.cn/MulanPSL2 
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 
 * See the Mulan PSL v2 for more details.
 */ 

#include "SWIGJavaInterfaceFileVisitor.h"
#include <iostream>

SWIGJavaInterfaceFileVisitor::SWIGJavaInterfaceFileVisitor(
    const std::string& outputDir, 
    const std::string& fileName, 
    CppLangTypeNameVisitor* typeNameVisitor, 
    CppLangTypeHeaderVisitor* headerVisitor)
    : FileGenVisitor(outputDir, fileName)
    , typeNameVisitor_(typeNameVisitor)
    , headerVisitor_(headerVisitor) {
}

SWIGJavaInterfaceFileVisitor::~SWIGJavaInterfaceFileVisitor() {
}

void SWIGJavaInterfaceFileVisitor::visit(SpecificationNode& node) {
    std::string headerName = headerVisitor_->getFileName();
    std::string types = headerName.substr(0, headerName.find_last_of("."));
    content_ += "%module " + types + "Module\n\n";
    content_ += "%{\n";
    content_ += "#include \"" + types + ".h\"\n";
    content_ += "#include \"" + types + "TypeSupport.h\"\n";
    content_ += "#include \"dds_cpp_infrastructure.h\"\n";
    content_ += "#include \"dds_cpp_datawriter.h\"\n";
    content_ += "#include \"dds_cpp_datareader.h\"\n";
    content_ += "#include \"dds_cpp_topic.h\"\n";
    content_ += "%}\n\n";

    content_ += "%include \"arrays_java.i\"\n";
    content_ += "%include \"std_string.i\"\n";
    content_ += "%include \"std_wstring.i\"\n";
    content_ += "%include \"std_vector.i\"\n";
    content_ += "%include \"std_map.i\"\n\n";
    content_ += "%import \"travoddsjava.i\"\n\n";

    content_ += "%typemap(javaimports) SWIGTYPE\n";
    content_ += "%{\n";
    content_ += "import org.travodds.*;\n";
    content_ += "%}\n\n";

    content_ += "%pragma(java) jniclassimports=%{\n";
    content_ += "import org.travodds.*;\n";
    content_ += "%}\n\n";

    // 递归访问子节点
    if (node.definitions_) {
        node.definitions_->accept(*this);
    }
    // 接口文件包含的头文件
    content_ += "%include \"" + headerName + "\"\n\n";
    // 将_content写入文件
    writeToFile();
}

void SWIGJavaInterfaceFileVisitor::generateTypeSupport(const std::string& shortName, const std::string& fullName) {
    content_ += "%template(" + shortName + "TypeSupport) TypedTypeSupport<" + fullName + "TypeSupport>;\n";
}

void SWIGJavaInterfaceFileVisitor::generateDataWriter(const std::string shortName, const std::string& fullName) {
    content_ += "%template(" + shortName + "DataWriter) TypedDataWriter<" + fullName + ">;\n";
}

void SWIGJavaInterfaceFileVisitor::generateDataReader(const std::string shortName, const std::string& fullName) {
    content_ += "%template(" + shortName + "DataReader) TypedDataReader<" + fullName + ">;\n";
}

void SWIGJavaInterfaceFileVisitor::visit(StructDefNode& node) {
    typeName_ = typeNameVisitor_->findName(&node);
    // 递归访问子节点
    if (node.members_) {
        node.members_->accept(*this);
    }
    std::string shortName = typeNameVisitor_->findShortName(&node);
    // 包装TypeSupport
    generateTypeSupport(shortName, typeName_);
    // 生成DataWriter和DataReader
    generateDataWriter(shortName, typeName_);
    generateDataReader(shortName, typeName_);
}

void SWIGJavaInterfaceFileVisitor::visit(UnionDefNode& node) {
    typeName_ = typeNameVisitor_->findName(&node);
    // 递归访问子节点
    if (node.cases_) {
        node.cases_->accept(*this);
    }
    std::string shortName = typeNameVisitor_->findShortName(&node);
    // 包装TypeSupport
    generateTypeSupport(shortName, typeName_);
    // 生成DataWriter和DataReader
    generateDataWriter(shortName, typeName_);
    generateDataReader(shortName, typeName_);
}

std::string SWIGJavaInterfaceFileVisitor::normalizeTemplateTypeName(const std::string& firstName, const std::string& secondName) {
    // firstName和secondName首字母大写
    std::string firstSeg = firstName;
    firstSeg[0] = std::toupper(firstSeg[0]);
    std::string secondSeg = secondName;
    if (!secondName.empty()) {
        secondSeg[0] = std::toupper(secondSeg[0]);
    }
    std::string normalizedName = firstSeg + secondSeg;
    // 去掉所有的空格
    std::string::size_type pos = 0;
    while ((pos = normalizedName.find(' ', pos)) != std::string::npos) {
        normalizedName.erase(pos, 1);
    }
    return normalizedName;
}

void SWIGJavaInterfaceFileVisitor::visit(MemberNode& node) {
    // 处理sequence和map
    TypeSpecNode* memberType = node.type_;
    SequenceTypeNode* seqType = dynamic_cast<SequenceTypeNode*>(memberType);
    if (seqType) {
        TypeSpecNode* seqElemType = seqType->type_;
        // 忽略基础数据类型的sequence
        BaseTypeNode* baseType = dynamic_cast<BaseTypeNode*>(seqElemType);
        if (baseType) {
            return;
        }
        // 忽略string和wstring类型的sequence
        StringTypeNode* stringType = dynamic_cast<StringTypeNode*>(seqElemType);
        WideStringTypeNode* wstringType = dynamic_cast<WideStringTypeNode*>(seqElemType);
        if (stringType || wstringType) {
            return;
        }
        if (seqElemType) {
            std::string seqElemTypeName = typeNameVisitor_->findShortName(seqElemType);
            std::string seqElemFullTypeName = typeNameVisitor_->findName(seqElemType);
            std::string normalizedTypeName = normalizeTemplateTypeName(seqElemTypeName, "");
            content_ += "%template(" + normalizedTypeName + "Seq) std::vector<" + seqElemFullTypeName + ">;\n";
        }
        return;
    }
    MapTypeNode* mapType = dynamic_cast<MapTypeNode*>(memberType);
    if (mapType) {
        TypeSpecNode* keyType = mapType->keyType_;
        TypeSpecNode* valueType = mapType->valueType_;
        // 忽略基础数据类型的map
        BaseTypeNode* baseKeyType = dynamic_cast<BaseTypeNode*>(keyType);
        BaseTypeNode* baseValueType = dynamic_cast<BaseTypeNode*>(valueType);
        StringTypeNode* stringKeyType = dynamic_cast<StringTypeNode*>(keyType);
        StringTypeNode* stringValueType = dynamic_cast<StringTypeNode*>(valueType);
        WideStringTypeNode* wstringKeyType = dynamic_cast<WideStringTypeNode*>(keyType);
        WideStringTypeNode* wstringValueType = dynamic_cast<WideStringTypeNode*>(valueType);
        if ((baseKeyType || stringKeyType || wstringKeyType) && (baseValueType || stringValueType || wstringValueType)) {
            return;
        }
        // 忽略string和wstring类型的map
        if (keyType && valueType) {
            std::string keyTypeName = typeNameVisitor_->findShortName(keyType);
            std::string keyFullTypeName = typeNameVisitor_->findName(keyType);
            std::string valueTypeName = typeNameVisitor_->findShortName(valueType);
            std::string valueFullTypeName = typeNameVisitor_->findName(valueType);
            std::string normalizedTypeName = normalizeTemplateTypeName(keyTypeName, valueTypeName);
            content_ += "%template(" + normalizedTypeName + "Map) std::map<" + keyFullTypeName + ", " + valueFullTypeName + ">;\n";
        }
        return;
    }
    bool isArray = node.arrayDims_ && node.arrayDims_->nodes_.size() > 0;
    if (isArray) {
        // 忽略一维基本数据类型数组
        BaseTypeNode* baseType = dynamic_cast<BaseTypeNode*>(memberType);
        if (baseType && node.arrayDims_->nodes_.size() == 1) {
            return;
        }
        // ignore本属性
        content_ += "%ignore " + typeName_ + "::" + *node.identifier_ + ";\n";
        // extend类型的get/set方法，参数的个数与数组的维度有关
        std::string memberName = *node.identifier_;
        std::string memberType = typeNameVisitor_->findName(node.type_);
        std::string memberShortType = typeNameVisitor_->findShortName(node.type_);
        // extend
        content_ += indent() + "%extend " + typeName_ + " {\n";
        ++indentLevel_;
        content_ += indent() + memberShortType + " get" + memberName + "(";
        for (size_t i = 0; i < node.arrayDims_->nodes_.size(); i++) {
            content_ += "int index" + std::to_string(i);
            if (i != node.arrayDims_->nodes_.size() - 1) {
                content_ += ", ";
            }
        }
        content_ += ") {\n";
        content_ += indent() + "    return self->" + memberName;
        for (size_t i = 0; i < node.arrayDims_->nodes_.size(); i++) {
            content_ += "[index" + std::to_string(i) + "]";
        }
        content_ += ";\n";
        content_ += indent() + "}\n";
        // set方法
        content_ += indent() + "void set" + memberName + "(";
        for (size_t i = 0; i < node.arrayDims_->nodes_.size(); i++) {
            content_ += "int index" + std::to_string(i);
            if (i != node.arrayDims_->nodes_.size() - 1) {
                content_ += ", ";
            }
        }
        content_ += ", const " + memberShortType + "& " + memberName + ") {\n";
        content_ += indent() + "    self->" + memberName;
        for (size_t i = 0; i < node.arrayDims_->nodes_.size(); i++) {
            content_ += "[index" + std::to_string(i) + "]";
        }
        content_ += " = " + memberName + ";\n";
        content_ += indent() + "}\n";
        --indentLevel_;
        content_ += indent() + "}\n";
        return;
    }
}